/*
 * Created by SharpDevelop.
 * User: Michael
 * Date: 13/09/2007
 * Time: 10:03 PM
 * 
 * To change this template use Tools | Options | Coding | Edit Standard Headers.
 */
using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using System.IO;

namespace SudokuSolver
{
	class Program
	{
		private static SudokuGame _TheGame;
		
		
		
		private static string ToCoord(int col, int row)
		{
			string returnString;
			
			returnString = ((char)(col + 64)).ToString();
			returnString += row.ToString();
			return returnString;
		}
		
		private static void SetUpGame()
		{
			for(int i = 1; i <= 9; i++)
			{
				for(int j = 1; j <= 9; j++)
				{
					Console.Clear();
					List<string> GameAsString = _TheGame.DrawGame();
					//Draw it
					Console.WriteLine("  ABC DEF GHI");
					int count = 0;
					string[] lineNumbers = new string[] {"1 ","2 ","3 ","  ","4 ","5 ","6 ","  ","7 ","8 ","9 "};
					foreach(string s in GameAsString)
					{
						Console.WriteLine(lineNumbers[count++] + s);
					}
					
					Console.WriteLine("Enter a value for {0} or press enter to leave blank", ToCoord(j, i));
					string tempString = Console.ReadLine();
					if(!(tempString == ""))
					{
						char tempChar = tempString[0];
						int cellValue = (int)tempChar - 48;
						
						_TheGame.Columns[j - 1].Cells[i - 1].Value = cellValue;
					}
				}
			}
		}
		
		private static void SetUpGame(string gameCode)
		{
			//gamecode is an 81 char long string
			int thisChar = 0;
			foreach(Group row in _TheGame.Rows)
			{
				foreach(Cell cell in row.Cells)
				{
					if(gameCode[thisChar] != 0)
					{
						int thisValue;
						if(!int.TryParse(gameCode[thisChar].ToString(), out thisValue))
							throw new Exception("Invalid Sudoku code!");
						cell.Value = thisValue;
						thisChar++;
					}
				}
			}
		}

		private static void GameUpdated(object sender, EventArgs e)
		{
			DisplayGame();
			System.Threading.Thread.Sleep(100);
		}
		
		private static void DisplayGame()
		{
			Console.Clear();
			List<string> GameAsString = _TheGame.DrawGame();
			//Draw it
			Console.WriteLine("  ABC DEF GHI");
			int count = 0;
			string[] lineNumbers = new string[] {"1 ","2 ","3 ","  ","4 ","5 ","6 ","  ","7 ","8 ","9 "};
			foreach(string s in GameAsString)
			{
				Console.WriteLine(lineNumbers[count++] + s);
			}			
		}
		
		public static void Main(string[] args)
		{
			do {
			_TheGame = new SudokuGame();
			
			_TheGame.Updated += new EventHandler(GameUpdated);
			
			Console.WriteLine("Welcome to Sudoku Solver!");
			
			//Set up the Game
			string code = "";
			if(args.Length == 0)
			{
				code = "";
			}
			else if(args[0].Length == 81)
			{
				code = args[0];
			} 
			else if(Regex.IsMatch(args[0], ".*[.]txt$"))
			{
				code = GetCodeFromFile(args[0]);
			}
			if(code == "")
			{
				SetUpGame();
			} else {
				SetUpGame(code);
			}
			try 
			{
				_TheGame.Solve();
				DisplayGame();
				
				if(_TheGame.Solved)
				{
					Console.WriteLine("Sudoku Solver wins again!");
				} else {
					Console.WriteLine("This sudoku is too hard... Try again with a newer version!");
					int found = _TheGame.CountFound();
					float percentage = ((float)found / 81) * 100;
					Console.WriteLine("{0} out of 81 found. ({1}%)", found, (int)percentage);
				}
			}
			catch (InvalidSudokuException ex)
			{
				Console.WriteLine("This Sudoku was found to be invalid.");
				Console.WriteLine(ex.Message);
				Console.WriteLine("Found by {0}", ex.SourceObject.ToString());
			}
			catch (Exception ex)
			{
				Console.WriteLine("An error occurred, Sudoku Solver must exit");
				Console.Write("Message was: ");
				Console.WriteLine(ex.Message);
			}
						
			Console.WriteLine("Press enter to start over or type 'exit' to quit");
			string input = Console.ReadLine();
			if(input.ToUpper() == "EXIT")
			{
				return;
			}
		} while(true);
		}
		
		private static string GetCodeFromFile(string filename)
		{
			StreamReader fileReader = new StreamReader(filename);
			List<string> codes = new List<string>();
			while(!fileReader.EndOfStream)
			{
				codes.Add(fileReader.ReadLine());
			}
			
			string input;
			int choice;
			do {
				do {
					Console.Write("There are {0} puzzles in this file, choose a number from 1 to {0}: ", codes.Count);
					input = Console.ReadLine();
				} while(!int.TryParse(input, out choice));
			} while((choice < 1) || (choice > codes.Count));
			do {
				Console.Clear();
				DisplayGameFromCode(codes[choice - 1]);
				do {
					do {
						Console.WriteLine("There are {0} puzzles in this file, choose a number from 1 to {0}: ", codes.Count);
						Console.WriteLine("(Or just press enter to solve this puzzle)");
						Console.Write("Entry: ");
						input = Console.ReadLine();
						if(input == "")
						{
							fileReader.Close();
							return codes[choice - 1];
						}
					} while(!int.TryParse(input, out choice));
				} while((choice < 1) || (choice > codes.Count));
			} while(true);
		}
		
		private static void DisplayGameFromCode(string code)
		{
			int index = 0;
			for(int rowBlock = 1; rowBlock <= 3; rowBlock++)
			{
				for(int row = 1; row <= 3; row++)
				{
					for(int columnBlock = 1; columnBlock <= 3; columnBlock++)
					{
						for(int cell = 1; cell <= 3; cell++)
						{
							if(code[index] == '0')
								Console.Write(" ");
							else
								Console.Write(code[index]);
							
							index++;
						}
						if(columnBlock != 3)
							Console.Write("|");
					}
					Console.WriteLine();
				}
				if(rowBlock != 3)
					Console.WriteLine("---+---+---");
			}
		}
	}
}
